<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>纹理贴图</title>
</head>

<body>
  <h3>将图片绘制到三维空间中</h3>
  <h3>error: - 图片出不来</h3>
  <canvas id="webgl" width="500" height="500" style="background-color: grey;"></canvas>

  <script id="vertexShader" type="x-shader/x-vertex">
      attribute vec4 a_pos;
      attribute vec2 a_TexCoord;//纹理坐标
      varying vec2 v_TexCoord;//插值后纹理坐标
      void main(){
        gl_Position =  a_pos;
        //纹理坐标插值计算
        v_TexCoord = a_TexCoord;
      }
  </script>

  <script id="fragmentShader" type="x-shader/x-fragment">
      //所有float类型数据的精度是highp
      precision highp float;
      // 接收插值后的纹理坐标
      varying vec2 v_TexCoord;
      // 图片数据
      uniform sampler2D u_Sampler;
      void main(){
        // 采集纹素，逐片元赋值像素值
        gl_FragColor = texture2D(u_Sampler,v_TexCoord);
      }
  </script>
  <script type="module">

    var canvas = document.getElementById("webgl");
    var gl = canvas.getContext("webgl");


    var vertexShaderSource = document.getElementById("vertexShader").innerText;
    var fragShaderSource = document.getElementById("fragmentShader").innerText;

    var program = initShader(gl, vertexShaderSource, fragShaderSource);


    // 从外部向顶点着色器内传输数据
    const aposLocation = gl.getAttribLocation(program, 'a_pos');
    var a_TexCoord = gl.getAttribLocation(program, 'a_TexCoord');
    var u_Sampler = gl.getUniformLocation(program, 'u_Sampler');


    /**
     *  四个顶点坐标，z为0 
     **/

    const data = new Float32Array([
      -0.5, 0.5,//左上角——v0
      -0.5, -0.5,//左下角——v1
      0.5, 0.5,//右上角——v2
      0.5, -0.5 //右下角——v3
    ]);

    /**
     * 创建UV纹理坐标数据textureData
     * 采集图片哪个位置
     **/
    var textureData = new Float32Array([
      0, 1,//左上角——uv0
      0, 0,//左下角——uv1
      1, 1,//右上角——uv2
      1, 0 //右下角——uv3
    ]);

    
    /**
     * 加载纹理图像像素数据
     **/
     var image = new Image();
    image.src = '1.jpg';//设置图片路径
    image.onload = textureFun;//图片加载成功后执行texture函数


    /**\
     * 创建缓冲区，向顶点着色器传入顶点位置
     **/
    var buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
    gl.vertexAttribPointer(aposLocation, 2, gl.FLOAT, false, 0, 0);//设置点为2位
    gl.enableVertexAttribArray(aposLocation);

    /**
      创建缓冲区，向顶点着色器传入顶点纹理坐标
    **/
    var textureBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, textureData, gl.STATIC_DRAW);
    gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 0, 0);//设置点为2位
    gl.enableVertexAttribArray(a_TexCoord);


    /**
     创建缓冲区textureBuffer，传入图片纹理数据，然后执行绘制方法drawArrays()
    **/
    function textureFun() {
      console.log("顶顶顶");
      //创建图片缓冲区
      var texture = gl.createTexture();
      gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); //纹理图片上下反转
      gl.activeTexture(gl.TEXTURE0);//激活0号纹理单元TEXTURE0
      gl.bindTexture(gl.TEXTURE_2D, texture);//绑定纹理缓冲区
      //设置纹理贴图填充方式(纹理贴图像素尺寸大于顶点绘制区域像素尺寸)
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
      //设置纹理贴图填充方式(纹理贴图像素尺寸小于顶点绘制区域像素尺寸)
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
      //设置纹素格式，jpg格式对应gl.RGB
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
      gl.uniform1i(u_Sampler, 0);//纹理缓冲区单元TEXTURE0中的颜色数据传入片元着色器
      // 进行绘制
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
    }


    // gl.drawArrays(gl.LINE_LOOP, 0, 4);//绘制矩形边框
    // gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);//绘制矩形填充


    function initShader(gl, vertexShaderSource, fragShaderSource) {
      //创建顶点着色器对象
      var vertexShader = gl.createShader(gl.VERTEX_SHADER);
      //创建片元着色器对象
      var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
      //引入顶点、片元着色器源代码
      gl.shaderSource(vertexShader, vertexShaderSource);
      gl.shaderSource(fragmentShader, fragShaderSource);
      //编译顶点、片元着色器
      gl.compileShader(vertexShader);
      gl.compileShader(fragmentShader);

      //创建程序对象program
      var program = gl.createProgram();
      //附着顶点着色器和片元着色器到program
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      //链接program
      gl.linkProgram(program);
      //使用program
      gl.useProgram(program);
      //返回程序program对象
      return program;
    }
  </script>
</body>

</html>
